import { onLight, offLight } from './light_show';
function scatterParticles(particles: GameEntity[], type: string) {
    particles.forEach((particle) => {
        particle.particleVelocity = new GameVector3(
            (Math.random() - 0.5) * 45,
            (Math.random() - 0.5) * 45,
            (Math.random() - 0.5) * 45
        );
        particle.particleDamping = 0.96;
    });
}

function reformText(particles: GameEntity[], type: string) {
    particles.forEach((particle) => {
        const dx = particle.originalPos.x - particle.position.x;
        const dy = particle.originalPos.y - particle.position.y;
        const dz = particle.originalPos.z - particle.position.z;

        particle.particleVelocity = new GameVector3(
            dx * 0.2,
            dy * 0.2,
            dz * 0.2
        );
        particle.particleDamping = 0.93;
    });
}
function explodeParticles(particles: GameEntity[], type: string) {
    particles.forEach((particle: GameEntity) => {
        const angle = Math.random() * Math.PI * 2;
        const power = Math.random() * 45 + 30;
        const verticalPower = Math.random() * 24 + 15;

        particle.particleVelocity = new GameVector3(
            Math.cos(angle) * power,
            verticalPower,
            Math.sin(angle) * power
        );

        particle.gravity = true;

        particle.particleLifetime = 1 + Math.random() * 2;
        particle.particleSize = [6, 4.5, 3, 0];

        particle.rotationVelocity = new GameVector3(
            (Math.random() - 0.5) * 10,
            (Math.random() - 0.5) * 10,
            (Math.random() - 0.5) * 10
        );
    });

    setTimeout(() => {
        particles.forEach((particle) => {
            particle.destroy();
        });

        if (type !== 'start') {
            // eslint-disable-next-line no-use-before-define
            Festival();
        }
    }, 5000);
}

function createTextParticlesWithExplosion(
    type = 'start',
    angle = -Math.PI / 2
) {
    let text, charWidth, baseX;
    if (type === 'start') {
        text = 'START';
        charWidth = 6;
        baseX = 254 / 2.5;
    } else {
        text = '2025  SUMMER  CREATIVE  FESTIVAL';
        charWidth = 1.2;
        baseX = 10;
    }
    const baseY = 80;
    const baseZ = -180;

    const particles: GameEntity[] = [];

    const charMap: Record<string, [number, number][]> = {
        '0': [
            [3, 0],
            [6, 0],
            [9, 0],
            [0, 3],
            [12, 3],
            [0, 6],
            [12, 6],
            [0, 9],
            [12, 9],
            [0, 12],
            [12, 12],
            [0, 15],
            [12, 15],
            [3, 18],
            [6, 18],
            [9, 18],
        ],
        '2': [
            [0, 0],
            [3, 0],
            [6, 0],
            [9, 0],
            [12, 0],
            [12, 3],
            [9, 6],
            [6, 9],
            [3, 12],
            [0, 15],
            [3, 15],
            [6, 15],
            [9, 15],
            [12, 15],
            [0, 18],
            [12, 18],
        ],
        '5': [
            [0, 0],
            [3, 0],
            [6, 0],
            [9, 0],
            [12, 0],
            [0, 3],
            [0, 6],
            [3, 6],
            [6, 6],
            [9, 6],
            [12, 9],
            [12, 12],
            [0, 15],
            [3, 15],
            [6, 15],
            [9, 15],
            [0, 18],
            [3, 18],
            [6, 18],
            [9, 18],
        ],
        A: [
            [6, 0],
            [3, 3],
            [9, 3],
            [0, 6],
            [12, 6],
            [0, 9],
            [3, 9],
            [6, 9],
            [9, 9],
            [12, 9],
            [0, 12],
            [12, 12],
            [0, 15],
            [12, 15],
            [0, 18],
            [12, 18],
        ],
        C: [
            [3, 0],
            [6, 0],
            [9, 0],
            [0, 3],
            [12, 3],
            [0, 6],
            [0, 9],
            [0, 12],
            [0, 15],
            [12, 15],
            [3, 18],
            [6, 18],
            [9, 18],
        ],
        E: [
            [0, 0],
            [3, 0],
            [6, 0],
            [9, 0],
            [12, 0],
            [0, 3],
            [0, 6],
            [3, 6],
            [6, 6],
            [9, 6],
            [0, 9],
            [0, 12],
            [3, 12],
            [6, 12],
            [9, 12],
            [12, 12],
        ],
        F: [
            [0, 0],
            [3, 0],
            [6, 0],
            [9, 0],
            [12, 0],
            [0, 3],
            [0, 6],
            [3, 6],
            [6, 6],
            [9, 6],
            [0, 9],
            [0, 12],
            [0, 15],
            [0, 18],
        ],
        I: [
            [6, 0],
            [6, 3],
            [6, 6],
            [6, 9],
            [6, 12],
            [6, 15],
            [6, 18],
        ],
        M: [
            // 左侧垂直线 (精简)
            [0, 0],
            [0, 5],
            [0, 10],
            [0, 15],
            [0, 20],

            // 右侧垂直线 (精简)
            [27, 0],
            [27, 5],
            [27, 10],
            [27, 15],
            [27, 20],

            // 优化的V形连接 (更连贯的斜线)
            [0, 0],
            [5, 7],
            [10, 12],
            [13, 14], // 左上到中心
            [13, 14],
            [16, 12],
            [22, 7],
            [27, 0], // 中心到右上

            // 底部连接线
            [0, 20],
            [13, 10],
            [27, 20],

            // 关键点加强
            [13, 14],
            [13, 15],
            [13, 16], // 中心加强
        ],
        R: [
            [0, 0],
            [3, 0],
            [6, 0],
            [9, 0],
            [0, 3],
            [12, 3],
            [0, 6],
            [6, 6],
            [9, 6],
            [0, 9],
            [6, 9],
            [9, 9],
            [0, 12],
            [6, 12],
            [12, 12],
            [0, 15],
            [6, 15],
            [12, 15],
            [0, 18],
            [6, 18],
            [12, 18],
        ],
        S: [
            [3, 0],
            [6, 0],
            [9, 0],
            [0, 3],
            [12, 3],
            [0, 6],
            [3, 9],
            [6, 9],
            [9, 9],
            [12, 12],
            [0, 15],
            [12, 15],
            [3, 18],
            [6, 18],
            [9, 18],
        ],
        T: [
            [0, 0],
            [3, 0],
            [6, 0],
            [9, 0],
            [12, 0],
            [6, 3],
            [6, 6],
            [6, 9],
            [6, 12],
            [6, 15],
            [6, 18],
        ],
        U: [
            [0, 0],
            [0, 3],
            [0, 6],
            [0, 9],
            [0, 12],
            [0, 15],
            [12, 0],
            [12, 3],
            [12, 6],
            [12, 9],
            [12, 12],
            [12, 15],
            [3, 18],
            [6, 18],
            [9, 18],
        ],
        V: [
            [0, 0],
            [0, 3],
            [0, 6],
            [0, 9],
            [0, 12],
            [6, 15],
            [12, 0],
            [12, 3],
            [12, 6],
            [12, 9],
            [12, 12],
        ],
        L: [
            [0, 0],
            [0, 1],
            [0, 2],
            [0, 3],
            [0, 4],
            [0, 5],
            [0, 6],
            [0, 7],
            [0, 8],
            [0, 9],
            [0, 10],
            [0, 11],
            [0, 12],
            [0, 13],
            [0, 14],
            [0, 15],
            [0, 16],
            [0, 17],

            [2, 17],
            [3, 17],
            [4, 17],
            [5, 17],
            [6, 17],
            [7, 17],
            [8, 17],
            [9, 17],
            [10, 17],
            [11, 17],

            [1, 16],
            [1, 17],
            [2, 15],
            [2, 16],
            [2, 17],
        ],
        ' ': [], // 空格
    };

    let currentX = baseX;

    for (const char of text) {
        if (char === ' ') {
            currentX += charWidth;
            continue;
        } else {
            currentX += 1;
        }

        const points: [number, number][] = charMap[char] || [];
        let maxNum = 0;

        points.forEach(([dx, dy]: [number, number]) => {
            maxNum = Math.max(maxNum, dx);
            const random1 = Math.random();
            const random2 = Math.random();
            const random3 = Math.random();

            const cosA = Math.cos(angle);
            const sinA = Math.sin(angle);
            const x = currentX + dx * 0.5;
            const z = baseZ;

            const rotatedX = x * cosA + z * sinA;
            const rotatedZ = -x * sinA + z * cosA;

            const particle = world.createEntity({
                mesh: 'mesh/单元方块.vb',
                meshScale: new GameVector3(0.07, 0.07, 0.07),
                gravity: false,
                collides: false,
                position: new GameVector3(rotatedX, 0, rotatedZ),
                particleSize: [3, 3, 3, 3],
                particleRate: 300,
                particleLifetime: 1,
                particleColor: [
                    new GameRGBColor(
                        Math.floor(random1 * 255),
                        Math.floor(random2 * 255),
                        Math.floor(random3 * 255)
                    ),
                    new GameRGBColor(
                        Math.floor(random1 * 255),
                        Math.floor(random2 * 255),
                        Math.floor(random3 * 255)
                    ),
                    new GameRGBColor(
                        Math.floor(random1 * 255),
                        Math.floor(random2 * 255),
                        Math.floor(random3 * 255)
                    ),
                    new GameRGBColor(
                        Math.floor(random1 * 255),
                        Math.floor(random2 * 255),
                        Math.floor(random3 * 255)
                    ),
                ],
                meshColor: new GameRGBAColor(0, 0, 0, 0),
            });
            if (!particle) {
                return;
            }
            // particle.addTag(text-particle);
            particle.velocity.copy(
                new GameVector3(0, (baseY - dy * 0.5) / 12, 0).scale(0.2)
            );
            setTimeout(function () {
                particle.velocity.set(0, 0, 0);
                particle.particleRate = 10;
                particle.particleLifetime = 999;
            }, 6000);

            particle.originalPos = new GameVector3(
                currentX + dx * 0.5,
                baseY - dy * 0.5,
                baseZ
            );
            particles.push(particle);
        });

        currentX += charWidth + maxNum / 2;
    }

    const animationSequence: {
        delay: number;
        action: (particles: GameEntity[], type: string) => void;
    }[] = [
        { delay: 4000, action: scatterParticles },
        { delay: 7000, action: reformText },
        { delay: 10000, action: explodeParticles },
    ];

    let currentStep = 0;

    function runNextAnimationStep(type: string) {
        if (currentStep < animationSequence.length) {
            const step = animationSequence[currentStep++];
            setTimeout(() => {
                step.action(particles, type);
                runNextAnimationStep(type);
            }, step.delay);
        }
    }

    setTimeout(function () {
        runNextAnimationStep(type);
    }, 8000);
}
const Festival = createTextParticlesWithExplosion;

console.clear();

/**
 * 字符形状对应的方块点位
 * 值为1，则显示方块
 * 值为0，则不显示方块
 * 以此来拼凑出字符的形状
 */
const charMap: { [key: string]: number[][] } = {
    '0': [
        [1, 1, 1],
        [1, 0, 1],
        [1, 0, 1],
        [1, 0, 1],
        [1, 1, 1],
    ],
    '1': [
        [0, 1, 0],
        [0, 1, 0],
        [0, 1, 0],
        [0, 1, 0],
        [0, 1, 0],
    ],
    '2': [
        [1, 1, 1],
        [0, 0, 1],
        [1, 1, 1],
        [1, 0, 0],
        [1, 1, 1],
    ],
    '3': [
        [1, 1, 1],
        [0, 0, 1],
        [1, 1, 1],
        [0, 0, 1],
        [1, 1, 1],
    ],
    '4': [
        [1, 0, 1],
        [1, 0, 1],
        [1, 1, 1],
        [0, 0, 1],
        [0, 0, 1],
    ],
    '5': [
        [1, 1, 1],
        [1, 0, 0],
        [1, 1, 1],
        [0, 0, 1],
        [1, 1, 1],
    ],
    '6': [
        [1, 1, 1],
        [1, 0, 0],
        [1, 1, 1],
        [1, 0, 1],
        [1, 1, 1],
    ],
    '7': [
        [1, 1, 1],
        [0, 0, 1],
        [0, 0, 1],
        [0, 0, 1],
        [0, 0, 1],
    ],
    '8': [
        [1, 1, 1],
        [1, 0, 1],
        [1, 1, 1],
        [1, 0, 1],
        [1, 1, 1],
    ],
    '9': [
        [1, 1, 1],
        [1, 0, 1],
        [1, 1, 1],
        [0, 0, 1],
        [1, 1, 1],
    ],
    ' ': [
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
    ],
};

/**
 * 渲染一个字符
 * @param char 需渲染的字符
 * @param position 字符左上角位置
 */
function renderOneChar(char: string, position: GameVector3) {
    // 获取字符对应的方块点位，点位数据为二维数组
    const charData = charMap[char];
    // 遍历点位二维数组
    for (let i = 0; i < charData.length; i++) {
        const row = charData[i];
        // 遍历点位第i行
        for (let j = 0; j < row.length; j++) {
            const value = row[j];
            // 每一行方块的x坐标，随着列数增加而增加
            const z = position.z + j;
            // 每一行方块的y坐标，随着行数增加而降低
            const y = position.y - i;
            // 每一行方块的z坐标相同
            const { x } = position;
            if (value === 0) {
                // 值为0，则不显示方块
                voxels.setVoxelId(x, y, z, 0);
            } else {
                voxels.setVoxel(x, y, z, 'red_light');
            }
        }
    }
}

/**
 * 渲染一个字符串
 * @param str 需渲染的字符串
 * @param position 字符串第一个字符的左上角位置
 */
function renderString(str: string, position: GameVector3) {
    // 遍历每个字符，依次渲染
    for (let i = 0; i < str.length; i++) {
        // 观察charMap可知每个字符占用宽度为3，再加上字符间应有间距,因此每个字符的x要相距4
        const pos = position.add(new GameVector3(0, 0, 4 * i));
        renderOneChar(str[i], pos);
    }
}
async function voxel_countdown() {
    world.lightMode = 'manual';
    for (let i = 3; i >= 0.5; i -= 0.1) {
        world.sunLight = new GameRGBColor(i, i, i);
        await sleep(64);
    }
    await offLight();

    renderString('10', new GameVector3(134, 50, 124));
    await sleep(1000);
    renderString('  ', new GameVector3(134, 50, 124));
    for (let i = 9; i >= 0; i--) {
        renderString(String(i), new GameVector3(134, 50, 126));
        await sleep(1000);
    }
    renderString(' ', new GameVector3(134, 50, 126));
    await Festival();
    await sleep(40 * 1000);
    await onLight();
    for (let i = 0.5; i <= 3; i += 0.1) {
        world.sunLight = new GameRGBColor(i, i, i);
        await sleep(64);
    }
    world.lightMode = 'natural';
}

export { voxel_countdown };
